import 'package:boss/color_constant.dart';
import 'package:boss/textStyle/text_style.dart';
import 'package:hi_common/hi_common.dart';
import 'package:bot_toast/bot_toast.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';

class PopupMenuButton extends StatefulWidget {
  final Widget child;
  final List<String> items;
  final int index;
  final ValueChanged<int> onItemTap;
  final double popupHeight;
  final double popupWidth;
  final IndexedWidgetBuilder itemBuilder;
  final bool enabled;

  const PopupMenuButton({
    @required this.child,
    this.items,
    this.index,
    this.onItemTap,
    this.popupHeight,
    this.itemBuilder,
    this.popupWidth,
    this.enabled = true,
    Key key,
  }) : super(key: key);

  @override
  _PopupMenuButtonState createState() => _PopupMenuButtonState();
}

class _PopupMenuButtonState extends State<PopupMenuButton> {
  CancelFunc _cancelFunc;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () => popupMenu(context),
      child: widget.child,
    );
  }

  popupMenu(BuildContext context) {
    if (!widget.enabled) return;

    if (_cancelFunc != null) {
      _cancelFunc();
      return;
    }

    BotToast.showAttachedWidget(
      attachedBuilder: (_) {
        return PopupMenuList(
          popupWidth: widget.popupWidth,
          popupHeight: widget.popupHeight,
          items: widget.items,
          itemBuilder: widget.itemBuilder,
          index: widget.index,
          onItemTap: onItemTapHandle,
        );
      },
      wrapToastAnimation: (controller, cancel, Widget child) {
        _cancelFunc = cancel;

        return CustomAttachedAnimation(
          controller: controller,
          child: child,
        );
      },
      animationDuration: Duration(milliseconds: 300),
      enableSafeArea: false,
      targetContext: context,
      preferDirection: PreferDirection.bottomCenter,
      verticalOffset: 10,
      onlyOne: true,
      allowClick: false,
      ignoreContentClick: false,
      onClose: () {
        _cancelFunc = null;
      },
    );
  }

  onItemTapHandle(int index) {
    if (widget.onItemTap != null) {
      widget.onItemTap(index);
    }

    _cancelFunc();
  }
}

class PopupCustomButton extends StatefulWidget {
  final Widget child;
  final ToastBuilder popupWidgetBuilder;

  const PopupCustomButton({
    @required this.child,
    @required this.popupWidgetBuilder,
    Key key,
  }) : super(key: key);

  @override
  _PopupCustomButtonState createState() => _PopupCustomButtonState();
}

class _PopupCustomButtonState extends State<PopupCustomButton> {
  CancelFunc _cancelFunc;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () => _popupMenu(context),
      child: widget.child,
    );
  }

  void _popupMenu(BuildContext context) {
    if (_cancelFunc != null) {
      _cancelFunc();
      return;
    }

    BotToast.showAttachedWidget(
      attachedBuilder: (cancel) {
        return Material(
          color: Colors.transparent,
          child: ClipRRect(
            borderRadius: BorderRadius.circular(
              10.w,
            ),
            child: widget.popupWidgetBuilder(cancel),
          ),
        );
      },
      wrapToastAnimation: (controller, cancel, Widget child) {
        _cancelFunc = cancel;

        return CustomAttachedAnimation(
          controller: controller,
          child: child,
        );
      },
      animationDuration: Duration(milliseconds: 300),
      enableSafeArea: false,
      targetContext: context,
      preferDirection: PreferDirection.bottomCenter,
      verticalOffset: 10,
      onlyOne: true,
      allowClick: false,
      ignoreContentClick: false,
      onClose: () {
        _cancelFunc = null;
      },
    );
  }
}

class PopupMenuList extends StatefulWidget {
  final double popupHeight;
  final double popupWidth;
  final List<String> items;
  final IndexedWidgetBuilder itemBuilder;
  final int index;
  final ValueChanged<int> onItemTap;

  const PopupMenuList({
    this.popupWidth,
    this.popupHeight,
    this.items,
    this.itemBuilder,
    this.index,
    this.onItemTap,
    Key key,
  }) : super(key: key);

  @override
  _PopupMenuListState createState() => _PopupMenuListState();
}

class _PopupMenuListState extends State<PopupMenuList> {
  ScrollController scrollController;

  @override
  void initState() {
    super.initState();

    scrollController = ScrollController();

    WidgetsBinding.instance.addPostFrameCallback((_) => scrollCenterIndexOffset(widget.index));
  }

  scrollCenterIndexOffset(index) {
    if (widget.index == null) return;

    var maxScrollExtent = scrollController.position.maxScrollExtent;
    var minScrollExtent = scrollController.position.minScrollExtent;
    var viewportDimension = scrollController.position.viewportDimension;

    var itemHeight = 70.w;
    var centerOffsetTop = (itemHeight * index + itemHeight * (index + 1)) / 2;

    var offset = (centerOffsetTop - viewportDimension / 2.0).clamp(minScrollExtent, maxScrollExtent);

    scrollController.jumpTo(offset);
  }

  @override
  void dispose() {
    scrollController.dispose();
    scrollController = null;
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Material(
      color: Colors.transparent,
      child: ClipRRect(
        borderRadius: BorderRadius.circular(10),
        child: Container(
            width: widget.popupWidth ?? 210.w,
            height: widget.popupHeight,
            decoration: BoxDecoration(
              color: Colors.white,
              borderRadius: BorderRadius.circular(10),
            ),
            child: ListView.builder(
              controller: scrollController,
              shrinkWrap: widget.popupHeight == null,
              padding: EdgeInsets.zero,
              itemCount: widget.items?.length,
              itemExtent: 90.w,
              itemBuilder: (context, index) {
                if (widget.itemBuilder != null) {
                  return GestureDetector(
                    onTap: () {
                      if (widget.onItemTap != null) widget.onItemTap(index);
                    },
                    behavior: HitTestBehavior.translucent,
                    child: widget.itemBuilder(context, index),
                  );
                }

                return PopupMenuItem(
                  title: widget.items[index],
                  isSelected: index == widget.index,
                  onTap: () {
                    if (widget.onItemTap != null) widget.onItemTap(index);
                  },
                );
              },
            )),
      ),
    );
  }
}

class PopupMenuItem extends StatelessWidget {
  final VoidCallback onTap;
  final bool isSelected;
  final String title;

  const PopupMenuItem({
    @required this.title,
    this.onTap,
    this.isSelected = false,
    Key key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return InkWell(
      onTap: onTap,
      child: Container(
        alignment: Alignment.center,
        height: 70.w,
        decoration: BoxDecoration(
          color: isSelected ? Colors.white : Colors.transparent,
          borderRadius: BorderRadius.circular(isSelected ? 10.w : 0),
        ),
        child: Text(
          title,
          style: isSelected ? TextStyleConstant().origin_28 : TextStyleConstant().normal_1_28,
        ),
      ),
    );
  }
}

class CustomAttachedAnimation extends StatefulWidget {
  final AnimationController controller;
  final Widget child;

  const CustomAttachedAnimation({Key key, this.controller, this.child}) : super(key: key);

  @override
  _CustomAttachedAnimationState createState() => _CustomAttachedAnimationState();
}

class _CustomAttachedAnimationState extends State<CustomAttachedAnimation> {
  Animation<double> animation;

  @override
  void initState() {
    animation = CurvedAnimation(parent: widget.controller, curve: Curves.decelerate);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: widget.controller,
      child: widget.child,
      builder: (context, child) {
        return Opacity(
          opacity: animation.value,
          child: Container(
            decoration: BoxDecoration(
              boxShadow: [
                BoxShadow(
                  color: ColorConstant.shadow,
                  blurRadius: 7,
                  spreadRadius: 1,
                ),
              ],
              color: Colors.white,
              borderRadius: BorderRadius.circular(10.w),
            ),
            child: ClipRRect(
              borderRadius: BorderRadius.circular(10.w),
              child: child,
            ),
          ),
        );
      },
    );
  }
}
